home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
dnsconf
/
dns.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-30
|
10KB
|
389 lines
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "../misc/misc.h"
#include "dnsconf.h"
#include "internal.h"
#include "../paths.h"
extern DNSCONF_HELP_FILE help_dnsconf;
CONFIG_FILE f_boot (ETC_NAMED_BOOT,help_dnsconf
,CONFIGF_MANAGED|CONFIGF_OPTIONNAL|CONFIGF_PROBED);
static int dns_is_reverse(const char *str)
{
int ret = 0;
char buf[200];
strcpy (buf,str);
strupr (buf);
char *pt = strstr(buf,".IN-ADDR.ARPA");
if (pt != NULL){
if (pt[13] == '\0'){
ret = 1;
}
}
return ret;
}
PRIVATE void DNS::parse(const char *buf, const char *fpath, int noline)
{
char words[10][500];
for (int i=0; i<10; i++) words[i][0] = '\0';
int nb = sscanf (buf,"%s %s %s %s %s %s %s %s %s %s"
,words[0],words[1],words[2],words[3]
,words[4],words[5],words[6],words[7]
,words[8],words[9]);
if (strcmp(words[0],"directory")==0){
pathcfg.setfrom (words[1]);
}else if (strcmp(words[0],"cache")==0){
cachefiles.add (new CACHEFILE (words[1],words[2]));
}else if (strcmp(words[0],"primary")==0){
if (dns_is_reverse(words[1])){
primarys_rev.add (new PRIMARY_REV(words[1]
,words[2],pathcfg.get()));
}else{
primarys.add (new PRIMARY(words[1],words[2]
,pathcfg.get()));
}
}else if (strcmp(words[0],"secondary")==0){
const char *tbip[8];
for (int i=0; i<8; i++) tbip[i] = words[i+2];
secondarys.add (new SECONDARY (words[1],words[nb-1]
,tbip,nb-3));
}else if (strcmp(words[0],"forwarders")==0){
nbforward = nb - 1;
for (int f=1; f<nb; f++) forwarders[f-1].setfrom(words[f]);
}else if (strcmp(words[0],"slave")==0){
slave = 1;
}else{
xconf_error ("Invalid keyword %s, file %s line %d\n"
,words[0],fpath,noline);
}
}
/*
Add the reverse mapping for the loopback network
*/
PUBLIC void DNS::setlocalhost()
{
PRIMARY_REV *pri = new PRIMARY_REV;
pri->domainv.setfrom ("127.0.0");
pri->setfromv();
pri->file.setfrom ("127.0.0");
pri->addrec (new RECORD_IN_SOA);
pri->addrec (new RECORD_IN_NS);
pri->addrec (new RECORD_IN_PTR ("1","localhost."));
primarys_rev.add (pri);
}
PUBLIC DNS::DNS()
{
slave = 0;
pathcfg.setfrom ("/var/named");
nbforward = 0;
FILE *fin = f_boot.fopen ("r");
if (fin != NULL){
char buf[500];
int noline = 0;
while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
noline++;
strip_end (buf);
char *pt = str_skip(buf);
/* #Specification: dnsconf / /etc/named.boot / comments
Comments in /etc/named.boot are not preserve
by dnsconf
*/
if (*pt != '\0' && *pt != ';'){
parse (buf,f_boot.getpath(),noline);
}
}
}
}
/*
Return != 0 if the DNS is not configured at all
*/
PUBLIC int DNS::empty()
{
return primarys.getnb()==0 && primarys_rev.getnb()==0;
}
PUBLIC void DNS::basiccheck()
{
if (cachefiles.getnb()==0){
cachefiles.add (new CACHEFILE(".","root.cache"));
}
FQHOST rfq ("1.0.0.127.in-addr.arpa");
PRIMARY *rev = primarys_rev.getitem(rfq,NULL);
if (rev == NULL){
/* #Specification; dnsconf / check / local domain
Dnsconf make sure the domain
0.0.127.in-addr.arpa is defined. If not it is
added with a single PTR entry.
#
1 IN PTR localhost.
#
*/
setlocalhost();
}
}
/*
Write all configuration files of the DNS.
Return -1 if any error.
*/
PUBLIC int DNS::write ()
{
int ret = -1;
/* #Specification: dnsconf / writing /etc/named.boot
The file /etc/named.boot is rewritten everytime any
of the DNS files are rewritten. This give a hint
to netconf to instruct named to restart(reload) just
by looking at the revision date of /etc/named.boot.
*/
FILE *fout = f_boot.fopen ("w");
if (fout != NULL){
const char *cfg = pathcfg.get();
struct stat st;
if (stat(cfg,&st)==-1) mkdir (cfg,0755);
fprintf (fout,"directory\t%s\n",cfg);
for (int i=0; i<cachefiles.getnb(); i++){
CACHEFILE *c = cachefiles.getitem(i);
fprintf (fout,"cache\t%s\t%s\n",c->domain.get()
,c->path.get());
}
const char *named_dir = pathcfg.get();
ret = primarys.write(fout,named_dir);
ret = primarys_rev.write(fout,named_dir);
secondarys.write(fout,named_dir);
if (nbforward > 0){
fputs ("forwarders",fout);
for (int f=0; f<MAX_FORWARDERS; f++){
fputc (' ',fout);
fputs (forwarders[f].get(),fout);
}
fputc ('\n',fout);
}
if (slave) fprintf (fout,"slave\n");
fclose (fout);
}
return ret;
}
#if 0
static void qualify(
const char *fqhost,
char *host,
char *domain)
{
char *pt = strchr(fqhost,'.');
if (pt != NULL){
strcpy (domain,pt+1);
int len = (int)(pt-fqhost);
memcpy (host,fqhost,len);
host[len] = '\0';
}else{
strcpy (host,fqhost);
RESOLV res;
strcpy (domain,res.domain.get());
}
}
#endif
/*
Add or replace record (A and PTRs) for a host
*/
PUBLIC int DNS::set (
const char *fqhost, // Fully qualified name, or name
// relative to our own domain
const char *tbip[], // May set several IP number for
int nbip) // one host at once
{
/* #Specification: dnsconf / set a host / multiple IP
A host may have several IP number in the DNS. The
first one is known as the official one. So a
host may have several A record and several
corresponding PTR records.
*/
FQHOST fq (fqhost);
/* #Specification: dnsconf / setting new spec for a host
dnsconf use a fairly simple way to update a host
definition. It simply delete everything relate
to that host (A record and PTR record) and add
records in the proper primarys.
There is no chance, using this strategy, to keep the
original ordering of the record files. This is
why dnsconf always sort those before writing.
*/
unset (fqhost);
// Checking if this DNS is the primary for the domain
PRIMARY *pri = primarys.getitem(fq,NULL);
if (pri != NULL){
for (int i=0; i<nbip; i++){
pri->set (fq
,new RECORD_IN_A("dummy",tbip[i]));
}
}
PRIMARY *onerev = NULL;
for (int noip=0; noip < nbip; noip++){
const char *ip = tbip[noip];
IP_ADDR ipa;
ipa.setfrom(ip);
char revdom[40];
ipa.setrev(revdom);
FQHOST rfq (revdom);
PRIMARY *rev = primarys_rev.getitem(rfq,NULL);
if (rev != NULL){
char fqdn[PATH_MAX];
fq.formatfull (fqdn);
rev->set (rfq
,new RECORD_IN_PTR("dummy",fqdn));
onerev = rev;
}
}
int ret = -1;
if (pri != NULL || onerev != NULL) ret = 0;
return ret;
}
/*
Add or replace NS record for a host
Return -1 if the information could not be added to any domain.
*/
PUBLIC int DNS::setns (
const SSTRING &fqhost, // Fully qualified name, or name
// relative to our own domain
const SSTRINGS &tbns) // May set several NS for
// one host at once
{
/* #Specification: dnsconf / set a domain / multiple NS
A domain may have several NS record in the DNS. The
first one is known as the official one. The others
are secondaries.
*/
FQHOST fq (fqhost);
unsetns (fqhost);
int ret = -1;
for (int i=0; i<2; i++){
/* #Specification: dnsconf / domain and sub-domain
A DNS may hold information for a domain and
for sub-domain. When updating the NS records
of a sub-domain, we also update NS records
in the parent domain automaticly.
*/
PRIMARY *pri = primarys.getitem(fq,NULL,i);
if (pri != NULL){
int nbns = tbns.getnb();
for (int i=0; i<nbns; i++){
SSTRING *ns = tbns.getitem(i);
if (!ns->is_empty()){
pri->set (fq
,new RECORD_IN_NS("dummy"
,ns->get()));
}
}
ret = 0;
}
}
return ret;
}
/*
Add or replace MX record for a host
*/
PUBLIC int DNS::setmx (
const SSTRING &fqhost, // Fully qualified name, or name
// relative to our own domain
const SSTRINGS &tbmx) // May set several MX for
// one host at once
{
/* #Specification: dnsconf / set a host / multiple MX
A host may have several MX record in the DNS. dnsconf
automaticly assign a priority number based on the
order the different MXs are given.
*/
FQHOST fq (fqhost);
unsetmx (fqhost);
PRIMARY *pri = primarys.getitem(fq,NULL);
if (pri != NULL){
int nbmx = tbmx.getnb();
for (int i=0; i<nbmx; i++){
SSTRING *mx = tbmx.getitem(i);
if (!mx->is_empty()){
pri->set (fq
,new RECORD_IN_MX("dummy"
,i*5+5,mx->get()));
}
}
}
return (pri != NULL) ? 0 : -1;
}
/*
Remove all reference to a host in the DNS
*/
PUBLIC void DNS::unset (const char *fqhost)
{
FQHOST fq (fqhost);
char hostpart[200];
PRIMARY *pri = primarys.getitem(fq,hostpart);
if (pri != NULL){
pri->unset (new RECORD_IN_A(hostpart,"1.1.1.1"));
}
char full[200];
fq.formatfull (full);
for (int i=0; i<primarys_rev.getnb(); i++){
PRIMARY *pri = primarys_rev.getitem(i);
pri->unset (new RECORD_IN_PTR("1",full));
}
}
/*
Remove all reference to a host in the DNS
*/
PUBLIC void DNS::unsetns (const SSTRING &fqhost)
{
FQHOST fq (fqhost);
char hostpart[200];
for (int i=0; i<2; i++){
PRIMARY *pri = primarys.getitem(fq,hostpart,i);
if (pri != NULL){
pri->unset (new RECORD_IN_NS(hostpart,"dummy"));
}
}
}
/*
Remove all reference to a host in the DNS
*/
PUBLIC void DNS::unsetmx (const SSTRING &fqhost)
{
FQHOST fq (fqhost);
char hostpart[200];
PRIMARY *pri = primarys.getitem(fq,hostpart);
if (pri != NULL){
pri->unset (new RECORD_IN_MX(hostpart,0,"dummy"));
}
}
/*
Set a cname record (replace/add/remove)
*/
PUBLIC void DNS::setcname (const SSTRING &fqhost, const SSTRING &cname)
{
FQHOST fq (fqhost);
char hostpart[200];
PRIMARY *pri = primarys.getitem(fq,hostpart);
if (pri != NULL){
pri->unset (new RECORD_IN_CNAME(hostpart,"dummy"));
if (!cname.is_empty()){
pri->set (fq,new RECORD_IN_CNAME(hostpart
,cname.get()));
}
}
}